Cloud Storage の新機能 Bucket IP filtering で VPC と CIDR のアクセス制限を試してみた

Cloud Storage の新機能 Bucket IP filtering で VPC と CIDR のアクセス制限を試してみた

Clock Icon2024.12.01

Google Cloud データエンジニアのはんざわです。
クラスメソッドの Google Cloud Advent Calendar 2024 の 1 日目のブログです。

本日から 12 月 25 日までの約 1 ヶ月間、クラスメソッドメンバーが Google Cloud に関する記事を毎日お届けします。
ぜひ最後までご覧ください!

https://qiita.com/advent-calendar/2024/cm-google-cloud

本ブログでは、2024 年 11 月 14 日にプレビューとなった Cloud Storage の新機能 Bucket IP filtering を検証した内容を紹介したいと思います。

November 14, 2024

Bucket IP filtering とは?

概要

https://cloud.google.com/storage/docs/ip-filtering-overview

Cloud Storage の Bucket IP filtering は、リクエストの送信元 IP アドレスに基づいてバケットへのアクセスを制限するネットワークセキュリティ機能です。

この機能では、特定の IPv4 または IPv6 アドレスからのリクエストを許可するルールを定義し、バケット単位でアクセスを制限できます。これにより、CIDR を指定して、パブリックインターネットや特定の VPC ネットワークからのアクセスを許可することが可能です。

このセキュリティ機能を活用することで、バケットへの不正アクセスやデータ侵害のリスクを減らすことができます。

利用可能なリージョン

2024 年 11 月 29 日時点で、本機能が利用可能なリージョンは以下のとおりです。
残念ながら、現時点では東京リージョン(asia-northeast1)には対応していないので注意してください。

  • asia-south1
  • asia-south2
  • asia-southeast1
  • asia-southeast2
  • asia-east1
  • asia-east2
  • europe-west1
  • europe-west2
  • us-central1
  • us-east1
  • us-east4
  • us-west1

やりたいこと

今回やりたいことは、以下のとおりです。

  • us-central1 に検証に必要なリソースを準備する
  • VPC ネットワークを 1 つ作成
  • 作成した VPC ネットワークに対応するサブネットを 2 つ作成
  • それぞれのサブネットに Compute Engine をデプロイする
  • Cloud Storage のバケットに bucket IP filtering のルールを適用する
    • 作成した VPC ネットワークと、片方のサブネットの CIDR からのアクセスを許可する
  • 2 つのサブネットにデプロイした Compute Engine から、bucket IP filtering のルールを適用したバケットにアクセスしてみる

以下は、今回の構成を示したイメージ図です。

gcs-ip.drawio (1)

本ブログでは、特定の VPC ネットワークからのアクセス制御を検証します。
パブリックインターネットからのアクセス制御については、以下のブログを参考にしてください

https://dev.classmethod.jp/articles/google-cloud-storage-ip-filter/

検証

事前準備

最初に、検証に必要なリソースを準備します。

1. サービスアカウントの作成と必要な権限を付与

bucket IP filtering のルールを適用する際には、以下の 2 つの権限が必要です。

  • storage.buckets.create
  • storage.buckets.setIpFilter

事前定義済みロールだと roles/storage.admin の権限が必要になります。

# サービスアカウントの作成
gcloud iam service-accounts create sa-access-gcs

# roles/storage.admin の権限を付与
gcloud projects add-iam-policy-binding <PROJECT_ID> \
     --member="serviceAccount:sa-access-gcs@<PROJECT_ID>.iam.gserviceaccount.com" \
     --role="roles/storage.admin" \
     --condition None

2. VPC ネットワークの作成

サブネット作成モードをカスタムにした VPC ネットワークを作成します。

# カスタムモードの VPC を作成
gcloud compute networks create vpc-bucket-ip-filtering \
    --subnet-mode=custom

さらに、サブネットに配置した Compute Engine にアクセスする必要があるため、VPC ファイアウォールルールで ssh を許可します。

# ssh を許可する VPC ファイアウォールルールを作成
gcloud compute firewall-rules create bucket-ip-filtering-allow-ssh \
    --network vpc-bucket-ip-filtering \
    --action allow \
    --rules tcp:22

3. サブネットの作成

作成した VPC ネットワーク(vpc-bucket-ip-filtering)に 2 つのサブネットを作成します。
片方の CIDR を 10.0.0.0/28 に設定し、もう片方を 10.100.100.0/28 に設定します。

# 10.0.0.0/28 のサブネットを作成
gcloud compute networks subnets create subnet-bucket-ip-filtering-1 \
    --region=us-central1 \
    --network=vpc-bucket-ip-filtering \
    --range=10.0.0.0/28 \
    --enable-private-ip-google-access

# 10.100.100.0/28 のサブネットを作成
gcloud compute networks subnets create subnet-bucket-ip-filtering-2 \
    --region=us-central1 \
    --network=vpc-bucket-ip-filtering \
    --range=10.100.100.0/28 \
    --enable-private-ip-google-access

4. Compute Engine の作成

作成した 2 つのサブネットにそれぞれ Compute Engine インスタンスを作成します。

# 10.0.0.0/28 のサブネットに Compute Engine インスタンスを作成
gcloud compute instances create gce-bucket-ip-filtering-1 \
  --network="projects/<PROJECT_ID>/global/networks/vpc-bucket-ip-filtering" \
  --subnet="projects/<PROJECT_ID>/regions/us-central1/subnetworks/subnet-bucket-ip-filtering-1" \
  --zone="us-central1-a" \
  --scopes="storage-full" \
  --no-address \
  --service-account="sa-access-gcs@<PROJECT_ID>.iam.gserviceaccount.com"

# 10.100.100.0/28 のサブネットに Compute Engine インスタンスを作成
gcloud compute instances create gce-bucket-ip-filtering-2 \
  --network="projects/<PROJECT_ID>/global/networks/vpc-bucket-ip-filtering" \
  --subnet="projects/<PROJECT_ID>/regions/us-central1/subnetworks/subnet-bucket-ip-filtering-2" \
  --zone="us-central1-a" \
  --scopes="storage-full" \
  --no-address \
  --service-account="sa-access-gcs@<PROJECT_ID>.iam.gserviceaccount.com"

5. Cloud Storage バケットの作成とオブジェクトのアップロード

ルールを適用する Cloud Storage バケットを作成します。

# bucket IP filtering のルールを適用するバケットを作成
gcloud storage buckets create gs://bucket-ip-filtering-test \
  --location us-central1 \
  --soft-delete-duration 0 \
  --uniform-bucket-level-access

さらに、試しに参照するオブジェクトを事前にアップロードしておきます。

# テスト用のオブジェクトをアップロード
echo "Hello World" > sample.text
gcloud storage mv ./sample.text gs://bucket-ip-filtering-test

bucket IP filtering のルールを適用する

https://cloud.google.com/storage/docs/create-ip-filter

最後に、作成した Cloud Storage バケットに、bucket IP filtering のルールを適用します。
投稿日時点では、Google Cloud コンソールで bucket IP filtering の機能を利用することはできません。
この機能は、コマンドラインまたは REST API を使用してのみ設定可能です。

bucket IP filtering のルールを定義する JSON ファイルを作成します。
ルールを定義する項目の詳細は、上記のドキュメントを参考にしてください。

vpcNetworkSources のフィールドで VPC ネットワークからのアクセスを許可できます。
作成した VPC ネットワーク(vpc-bucket-ip-filtering)と片方のサブネットの CIDR(10.0.0.0/28)を networkallowedIpCidrRanges のフィールドに渡します。

bucket-ip-filtering-rules.json
{
    "mode": "Enabled",
    "vpcNetworkSources":
        [
            {
                "network": "projects/<PROJECT_ID>/global/networks/vpc-bucket-ip-filtering",
                "allowedIpCidrRanges":
                    [
                        "10.0.0.0/28"
                    ]
            }
        ]
}

JSON ファイルが用意できたら、以下のコマンドで bucket IP filtering のルールを適用します。

gcloud alpha storage buckets update gs://bucket-ip-filtering-test --ip-filter-file=bucket-ip-filtering-rules.json

アクセスしてみる

1. Google Cloud コンソール

まずは、Google Cloud コンソールからアクセスしてみます。
以下のキャプチャのとおり、ルールを適用したバケットへのリクエストが拒否されます。

スクリーンショット 2024-12-01 0.14.35

2. Cloud Shell

次に、Cloud Shell からアクセスしてみます。
以下のコマンド結果のとおり、ルールを適用したバケットへのリクエストが拒否されます。
エラーメッセージにも書いてあるように、IP filtering が適用されていることが分かると思います。

gcloud storage ls gs://bucket-ip-filtering-test/

ERROR: (gcloud.storage.ls) [<ユーザーアカウント>] does not have permission to access b instance [bucket-ip-filtering-test] (or it may not exist): There is an IP filtering condition that is preventing access to the resource. This command is authenticated as <ユーザーアカウント> which is the active account specified by the [core/account] property.

3. 許可されていない CIDR の Compute Engine

次に、ルールで許可されていない CIDR の Compute Engine(gce-bucket-ip-filtering-2)に SSH で接続し、バケットへアクセスしてみます。
Cloud Shell と同様に、ルールを適用したバケットへのリクエストが拒否されます。
VPC ネットワーク自体は許可されているものの、CIDR がルールで許可された範囲外であるため、リクエストが拒否されました。

@gce-bucket-ip-filtering-2:~$ gcloud storage ls gs://bucket-ip-filtering-test/

ERROR: (gcloud.storage.ls) [sa-access-gcs@<PROJECT_ID>.iam.gserviceaccount.com] does not have permission to access b instance [bucket-ip-filtering-test] (or it may not exist): There is an IP filtering condition that is preventing access to the resource. This command is authenticated as sa-access-gcs@<PROJECT_ID>.iam.gserviceaccount.com which is the active account specified by the [core/account] property.

4. 許可された CIDR の Compute Engine

最後に、ルールで許可された CIDR の Compute Engine(gce-bucket-ip-filtering-1) に SSH で接続し、バケットへアクセスしてみます。
ようやく、バケット内のオブジェクトを参照することができました!

@gce-bucket-ip-filtering-1:~$ gcloud storage ls gs://bucket-ip-filtering-test/
gs://bucket-ip-filtering-test/sample.text

オブジェクトの中身も問題なく参照できます。

@gce-bucket-ip-filtering-1:~$ gcloud storage cat gs://bucket-ip-filtering-test/sample.text
Hello World

VPC ネットワークと CIDR の両方が許可されていたため、リクエストが成功したと考えられます。

注意事項

1. 他の Google Cloud サービスへの影響

Cloud Storage で bucket IP filtering を有効化すると、一部の Google Cloud サービスへのアクセスが制限されます。
例えば、BigQuery では以下の操作が影響を受けます。

  • Cloud Storage からデータを BigQuery にロードする
  • BigQuery から Cloud Storage へテーブルデータをエクスポートする
  • BigQuery で Cloud Storage を外部テーブルとしてクエリを実行する
  • BigLake で Cloud Storage の構造化データにクエリを実行する
  • BigLake で Cloud Storage の非構造化データにクエリを実行する

詳細は、以下のドキュメントを参考にしてください。

参考:制限事項

試しに、許可された CIDR の Compute Engine(gce-bucket-ip-filtering-1)に SSH で接続し、BigQuery から Cloud Storage へテーブルデータをエクスポートするクエリを実行してみます。

@gce-bucket-ip-filtering-1:~$ bq query --nouse_legacy_sql \
'EXPORT DATA
  OPTIONS (
    uri="gs://bucket-ip-filtering-test/*.json",
    format="JSON",
    overwrite=true
  ) AS
SELECT "Hello World"'

Waiting on bqjob_r5cc7887cb069f712_0000019380e6dfec_1 ... (0s) Current status: DONE   

BigQuery error in query operation: Error processing job '<PROJECT_ID>:bqjob_r5cc7887cb069f712_0000019380e6dfec_1': Access Denied: BigQuery BigQuery: Permission denied while writing
data. There is an IP filtering condition that is preventing access to the resource. Please make sure gs://bucket-ip-filtering-test/000000000000.json is accessible via appropriate
IAM roles, e.g. Storage Object Viewer or Storage Object Creator.

上記のエラーメッセージは、bucket IP filtering によって BigQuery の操作が制限されたことを示しています。
この場合、Cloud Storage バケットに対するアクセスが IP フィルタリングルールで拒否されているため、BigQuery からの書き込みが失敗しています。

2. 誤設定やネットワーク変更によるロックアウト

誤ったルールを設定したり、ネットワーク変更によって IP アドレスが変わった場合、バケットへのアクセスがロックアウトされるリスクがあります。

そのような状況になった場合でも、回避方法が用意されています。
詳細は、以下の公式ドキュメントを参考にしてください。

https://cloud.google.com/storage/docs/bypass-ip-filter

まとめ

本ブログでは、Cloud Storage の新機能 Bucket IP filtering について紹介しました。
この機能を使用することで、これまでよりもバケットへの不正アクセスやデータ侵害のリスクを大幅に低減し、セキュリティを強化することができます。

従来、Cloud Storage への IP 制限を実現するには VPC Service Controls を利用する必要がありましたが、Bucket IP filtering を活用することで、よりシンプルに IP アドレスベースのアクセス制御を実現できるようになりました。

ただし、BigQuery など他の Google Cloud サービスに影響が出る場合や、誤設定によるバケットへのロックアウトといったリスクもあるため、利用には注意が必要です。

また、現時点では東京リージョン(asia-northeast1)で利用できないものの、今後の対応が期待されます。

明日 12/2 の投稿は suto-takeshi さんです。よろしくお願いします!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.